package multi_thread.master.tools;

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * @author Cheng Jun
 * Description: ThreadLocalRandom 比 Random 更高效，因为 Random 使用的 随机种子 seed 是全局共享，
 * ThreadLocalRandom 的随机种子，每个线程是独享的，在 Thread 类的最下面 threadLocalRandomSeed。
 * 利用了空间换时间的思想
 * ThreadLocalRandom、Random 两者都是线程安全的
 * @version 1.0
 * @date 2022/5/18 20:05
 * @see Random#next(int) 随机数算法的核心，用到了CAS自旋锁，如果高并发的场景下，很多线程自旋，就会引起CPU飙升
 * @see ThreadLocalRandom
 */
public class ThreadLocalRandomExample {

    public static void main(String[] args) {
        // 在高并发情况下，比较 Random 和 ThreadLocalRandom 生成随机数的效率，能差十几倍，并发越高，性能差异越明显
        Random random = new Random();
        // 注意不要使用 cachedThreadPool，线程太多的话，CPU飙升
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
        long startMilli = System.currentTimeMillis();
        for (int i = 0; i < 1_00; i++) {
            Runnable task = () ->{
                for (int j = 0; j < 1_00_000; j++) {
                    // ThreadLocalRandom.current().nextInt(100);
                    random.nextInt(100);
                }
            };
            fixedThreadPool.execute(task);
        }
        fixedThreadPool.shutdown();

        // while (!fixedThreadPool.isTerminated()){
        //     // 只要有任务没结束就死循环
        // }

        try {
            while (!fixedThreadPool.awaitTermination(100, TimeUnit.MILLISECONDS)){
                System.out.println("只要有任务没结束就死循环！");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long endMilli = System.currentTimeMillis();
        System.out.println("endMilli - startMilli = " + (endMilli - startMilli));
    }
}
